package services

import (
	"bytes"
	"fmt"
	"gitee.com/igolang/imoney/internal/app/system/entities"
	"gitee.com/igolang/imoney/internal/app/system/entities/constants"
	"gitee.com/igolang/imoney/internal/app/system/services/dict"
	"gitee.com/igolang/imoney/internal/app/system/tools"
	commonEntities "gitee.com/igolang/imoney/internal/common/entities"
	"gitee.com/igolang/imoney/internal/common/httpResp"
	"gitee.com/igolang/imoney/internal/core/client"
	"gitee.com/igolang/imoney/internal/models/dao"
	"gitee.com/igolang/imoney/internal/models/model"
	"gitee.com/igolang/pkg/xgorm"
	"gitee.com/igolang/pkg/xtime"
	"gitee.com/igolang/pkg/xutils"
	"github.com/gin-gonic/gin"
	"github.com/spf13/cast"
	"gorm.io/gen"
	"time"
)

var Post = &post{}

type post struct{}

func (s *post) List(ctx *gin.Context) (*commonEntities.ListResp, error) {
	var req entities.PostPageListReq
	if err := ctx.ShouldBind(&req); err != nil {
		return nil, err
	}
	req.Page()
	conds := s.formatListConds(req)
	total, err := dao.SysPost.Where(conds...).Count()
	if err != nil {
		return nil, err
	}
	result := &commonEntities.ListResp{
		Total: total,
		Rows:  make([]*model.SysPost, 0),
	}
	if total == 0 {
		return result, nil
	}
	list, err := dao.SysPost.Where(conds...).Limit(req.PageSize).Offset(req.Offset).Order(dao.SysPost.PostSort, dao.SysPost.PostID.Desc()).Find()
	if err != nil {
		return nil, err
	}
	result.Rows = list
	return result, nil
}

func (s *post) Export(ctx *gin.Context) (b *bytes.Buffer, err error) {
	var req entities.PostPageListReq
	if err = ctx.ShouldBind(&req); err != nil {
		return nil, err
	}

	conds := s.formatListConds(req)
	rows, err := dao.SysPost.Where(conds...).Rows()
	if err != nil {
		return nil, err
	}
	header := []string{"岗位序号", "岗位编码", "岗位名称", "岗位排序", "状态"}
	data := [][]string{header}
	dc := client.DB()
	commonStatusOptions, _ := dict.Get("sys_normal_disable")
	for rows.Next() {
		row := &model.SysPost{}
		if e := dc.ScanRows(rows, row); e != nil {
			continue
		}
		data = append(data, []string{
			cast.ToString(row.PostID),
			row.PostCode,
			row.PostName,
			cast.ToString(row.PostSort),
			dict.LabelOptions(commonStatusOptions, row.Status),
		})
	}
	fh := xutils.CreateExcelFileWithData(data)
	defer fh.Close()
	b, err = fh.WriteToBuffer()
	return
}

func (s *post) Save(ctx *gin.Context) (err error) {
	req := &model.SysPost{}
	if err = ctx.ShouldBindJSON(req); err != nil {
		return
	}
	if req.PostCode == "" || req.PostName == "" {
		return httpResp.ErrorCode(httpResp.ErrCodeInvalidParams)
	}
	if req.Status == "" {
		req.Status = constants.OkStatus
	}
	userInfo := tools.GetUserInfo(ctx)
	req.UpdateTime = xtime.Time(time.Now())
	req.UpdateBy = userInfo.User.UserName
	// 校验
	conds := make([]gen.Condition, 0)
	index := 0
	if req.PostID > 0 {
		conds = append(conds, dao.SysPost.PostID.Neq(req.PostID))
		index = 1
	}
	conds = append(conds, dao.SysPost.PostCode.Eq(req.PostCode))
	if count, _ := dao.SysPost.Select(dao.SysPost.PostID).Where(conds...).Count(); count > 0 {
		return fmt.Errorf("新增'%s'岗位失败，岗位编码已存在", req.PostName)
	}

	conds[index] = dao.SysPost.PostName.Eq(req.PostName)
	if count, _ := dao.SysPost.Select(dao.SysPost.PostID).Where(conds...).Count(); count > 0 {
		return fmt.Errorf("新增'%s'岗位失败，岗位名称已存在", req.PostName)
	}

	if req.PostID == 0 {
		req.CreateTime = xtime.Time(time.Now())
		req.CreateBy = userInfo.User.UserName
		return dao.SysPost.Create(req)
	}

	row, err := dao.SysPost.Where(dao.SysPost.PostID.Eq(req.PostID)).Take()
	if err != nil {
		return err
	}
	row.UpdateBy = req.UpdateBy
	row.UpdateTime = req.UpdateTime
	row.PostName = req.PostName
	row.PostCode = req.PostCode
	row.PostSort = req.PostSort
	row.Status = req.Status
	row.Remark = req.Remark
	data := xgorm.ModelToMap(row)
	_, err = dao.SysPost.Where(dao.SysPost.PostID.Eq(req.PostID)).Updates(data)
	return
}

func (s *post) formatListConds(req entities.PostPageListReq) []gen.Condition {
	conds := make([]gen.Condition, 0)
	if req.PostName != "" {
		conds = append(conds, dao.SysPost.PostName.Like(`%`+req.PostName+`%`))
	}
	if req.PostCode != "" {
		conds = append(conds, dao.SysPost.PostName.Eq(req.PostCode))
	}
	if req.Status != "" {
		conds = append(conds, dao.SysPost.Status.Eq(req.Status))
	}

	return conds
}
